class LogicAnalyzer { constructor( cc, style ) { this.cc = cc; this.style = Object.assign( { titleFontSize : 10, commentFontSize : 10, cellHeight : 32, palseHeight : 8, horizontalDiv : 8, horizontalShift : 1500, //top : 0, //利用可 //bottom : 0, //利用可 }, style ); this.etc = new Object(); this.etc.title = "JavaScript LOGIC ANALYZER by web6047"; cc.font = this.style.titleFontSize + "px''"; this.etc.titleX = cc.canvas.width - cc.measureText( this.etc.title ).width - this.style.titleFontSize; this.records = new Object(); this.backTm = 0; this.frame( 0 ); this.stopFlg = false; } hi( name, comment ) { //check. if( ! this.records[ name ] ) this.records[ name ] = new Array(); this.records[ name ].push( [ Date.now(), 1, comment ] ); } low( name, comment ) { this.records[ name ].push( [ Date.now(), 0, comment ] ); } stop() { this.stopFlg = true; this.trig(); } frame( tm ) { let diff = tm - this.backTm; this.backTm = tm; // if( ! this.stopFlg ) this.trig(); this.draw( this.cc ); requestAnimationFrame( this.frame.bind( this ) ); } trig() { let endTime = Date.now() + this.style.horizontalShift; this.lines = new Object(); for( let name in this.records ) { let record = this.records[ name ]; let drawPoints = new Array(); //2次元配列 [ [ x, y ], ... ] //x 下記yが起こった時間から現在時刻までの経過時間 //y 1:信号の立ち上がり、0:立ち下がり for( let j = 0; j < record.length; j++ ) { let sample = record[ j ]; let time = sample[ 0 ]; let method = sample[ 1 ]; let comment = sample[ 2 ]; let x = endTime - time; //波形にパルスをセット if( method == 1 ) { //立ち上がり drawPoints.push( [ x, 0 ] ); drawPoints.push( [ x, 1, comment ] ); } else { //立ち下がり //check. 画面左端に来たらパルスを削除予定(null) if( x < 0 ) { record[ j ] = null; record[ j - 1 ] = null; } drawPoints.push( [ x, 1 ] ); drawPoints.push( [ x, 0, comment ] ); } } //check. 削除実行 for( let j = record.length - 1; j >= 0; j-- ) { if( record[ j ] === null ) record.splice( j, 1 ); } this.lines[ name ] = drawPoints; } } draw( cc ) { //check. if( ! this.lines ) return; cc.save(); let height = ( Object.keys( this.lines ).length + 1) * this.style.cellHeight; let top = 0; //check. if( this.style.top != undefined ) top = this.style.top; else if( this.style.bottom != undefined ) top = cc.canvas.height - this.style.bottom -height; cc.translate( 0, top ); cc.font = this.style.titleFontSize + "px''"; cc.fillStyle = "black"; cc.fillRect( 0, 0, cc.canvas.width, height ); cc.strokeStyle = "lightgray"; cc.strokeRect( 0, 0, cc.canvas.width, height ); cc.fillStyle = "magenta"; cc.fillText( this.etc.title, this.etc.titleX, this.style.titleFontSize ); let i = 0; for( let name in this.lines ) { let drawPoints = this.lines[ name ]; cc.beginPath(); let gyBase = ( i + 1 ) * this.style.cellHeight; cc.moveTo( 0, gyBase ); for( let drawPoint of drawPoints ) { let diff = drawPoint[ 0 ]; let hiLow = drawPoint[ 1 ]; let comment = drawPoint[ 2 ]; let gx = cc.canvas.width - diff / this.style.horizontalDiv; let gy = gyBase - hiLow * this.style.palseHeight; cc.lineTo( gx, gy ); if( comment != null ) { cc.save(); cc.font = this.style.commentFontSize + "px''"; gx = gx - this.style.commentFontSize / 2; cc.fillStyle = "cyan"; if( hiLow ) { gy = gyBase - ( this.style.palseHeight + 3 ); cc.fillText( "↓" + comment, gx, gy ); } else { gy = gyBase + ( this.style.palseHeight + 3 ); cc.fillText( "↑" + comment, gx, gy ); } cc.restore(); } } //画面右端まで描画 if( drawPoints.length / 2 % 2 == 1 ) { //記録数が奇数なら、記録の最後はハイ cc.lineTo( cc.canvas.width, gyBase - this.style.palseHeight ); } else { //記録数が偶数なら、記録の最後はロー cc.lineTo( cc.canvas.width, gyBase ); } cc.strokeStyle = "cyan"; cc.stroke(); cc.fillStyle = "yellow"; cc.fillText( name + "↓", 4, gyBase - this.style.titleFontSize * 2 ); i++; } cc.restore(); } }